#ifndef SROS_DEVICE_DETAIL_DRIVER_IMPL_HPP
#define SROS_DEVICE_DETAIL_DRIVER_IMPL_HPP

#include <commons/type/ret.hpp>

#include "devices/detail/proto.hpp"
#include "devices/detail/define.hpp"

#include <stdint.h>
#include <memory>
#include <mutex>

const static uint16_t TPDO_0_ID = 0x1A00;   // TPDO 0 索引对象ID
const static uint16_t TPDO_1_ID = 0x1A01;   // TPDO 1 索引对象ID
const static uint16_t TPDO_2_ID = 0x1A02;   // TPDO 2 索引对象ID

namespace sros::device::detail
{
    class driver_impl
    {
    public:
        struct Param
        {
            uint8_t  id = 0;                // 驱动器id
            uint8_t  dir = 0;               // 电机运动方向  0: 正向  1: 反向
            uint16_t can_index = 0;         // 绑定的CAN口索引
            uint32_t resolution = 10000;    // 内置编码器分辨率
            uint16_t diameter = 100;        // 直径 mm
            float    gear_ratio = 1.0f;     // 减速比
        };

        // 上报的数据
        struct DataUp
        {
            uint32_t mode;                // 运动模式  位置模式:0 速度模式:1 电流模式:2
            int32_t  current;             // 反馈电流  mA
            int32_t  rpm;                 // 反馈的转速 rad/minn
            int32_t  spd;                 // 反馈的速度 mm/s
            int32_t  temperature;         // 电机温度  ℃s
            int32_t  pos;                 // 位置 mm
            int32_t  pulse;               // 脉冲累计值
            int32_t  max_current;         // 最大电流 mA
            int32_t  rate_current;        // 额定电流 mA
            int32_t  max_spd;             // 最大速度 mm/s
            int32_t  max_rpm;             // 最大转速 rad/min
            uint32_t error;               // 错误码
            uint32_t status_word;         // 状态字
            uint8_t  state;               // 状态 
            int32_t  nmt_status;          // nmt 状态
            bool     enable;              // 使能
        };

        // 下发的数据
        struct DataDown
        {
            int32_t rpm;     // 下发的转速
            int32_t spd;     // 下发的速度
            int32_t current; // 下发的电流
        };

        using EventCb = std::function<void(const uint8_t &ev_id, const uint32_t &data, const std::string &msg)>;

        driver_impl() = default;
        virtual ~driver_impl() = default;

        // 初始化
        virtual void init() = 0;

        // 运行
        virtual void run() = 0;

        // 关闭
        virtual void close() = 0;

        // 解析反馈报文
        virtual void parse(const device::proto::RspCanMsg &can_msg) {}

        // 故障清除
        virtual RetBool clear_error() { return {false}; }

        // 设置转速 mm/s
        virtual RetBool set_spd(const int32_t &spd) { return {false}; }

        // 设置电流 mA/s
        virtual RetBool set_current(const int32_t &current) { return {false}; }

        // 上下使能
        virtual RetBool set_enable(const bool &enable) { return {false}; }

        // 故障检测
        virtual void error_check() {}

        // 获取硬件信息
        inline Info info() { std::lock_guard<std::mutex> lck(info_mtx_); return info_;}

        // 获取参数
        inline Param param() { std::lock_guard<std::mutex> lck(param_mtx_); return param_; }

        // 获取上报数据
        inline DataUp data_up() { std::lock_guard<std::mutex> lck(data_up_mtx_); return data_up_; }

        // 获取实际下发数据
        inline DataDown data_down() { std::lock_guard<std::mutex> lck(data_down_mtx_); return data_down_; }

        // 更新硬件信息
        inline void set_info(const Info &info) { std::lock_guard<std::mutex> lck(info_mtx_); info_ = info; }

        // 更新参数
        inline void set_param(const Param &param) { std::lock_guard<std::mutex> lck(param_mtx_); param_ = param; }

        // 更新上报数据
        inline void set_data_up(const DataUp &data_up) { std::lock_guard<std::mutex> lck(data_up_mtx_); data_up_ = data_up; }

        // 设置下发数据
        inline void set_data_down(const DataDown &data_down) { std::lock_guard<std::mutex> lck(data_down_mtx_); data_down_ = data_down; }
        
        // 事件触发
        inline void install_event(EventCb cb) { event_cb_ = cb; }

    protected:
        std::mutex info_mtx_;
        std::mutex param_mtx_;
        std::mutex data_up_mtx_;
        std::mutex data_down_mtx_;

        Info       info_;
        Param      param_;
        DataUp     data_up_;
        DataDown   data_down_;
        EventCb    event_cb_;
    };
}

#endif